/*
 * RT MAP, Home of Professional MAP
 * Copyright 2018 Bit Main Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 */
package com.mz.springbootdemo.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * Description: 线程池配置
 * @author 盟主
 * @package ThreadPoolConfig
 * @date 2022/3/10 9:48 上午
*/
@Configuration
@EnableAsync
public class ThreadPoolConfig {

    /**
     * Description: 线程池注入
     * 一、处理任务的优先级：
     * 线程数量未达到corePoolSize，则新建一个线程(核心线程)执行任务
     * 线程数量达到了corePoolSize，则将任务移入队列等待
     * 队列已满，新建线程(非核心线程)执行任务
     * 队列已满，总线程数又达到了maximumPoolSize，就会抛出异常
     * 二、execute(Runable)方法执行过程
     * 如果此时线程池中的数量小于corePoolSize，即使线程池中的线程都处于空闲状态，也要创建新的线程来处理被添加的任务。
     * 如果此时线程池中的数量等于 corePoolSize，但是缓冲队列 workQueue未满，那么任务被放入缓冲队列。
     * 如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，并且线程池中的数量小于maxPoolSize，建新的线程来处理被添加的任务。
     * 如果此时线程池中的数量大于corePoolSize，缓冲队列workQueue满，并且线程池中的数量等于maxPoolSize，那么通过handler所指定的策略来处理此任务。也就是：处理任务的优先级为：核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize，如果三者都满了，使用handler处理被拒绝的任务。
     * 当线程池中的线程数量大于corePoolSize时，如果某线程空闲时间超过keepAliveTime，线程将被终止。这样，线程池可以动态的调整池中的线程数。
     * @return {@link ThreadPoolTaskExecutor}
     * @author 盟主
     * @date 2022/3/10 9:51 上午
    */
    @Bean(name = "asyncPoolTaskExecutor")
    public ThreadPoolTaskExecutor getAsyncThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 设置核心线程数 同时有多少个线程在执行任务
        taskExecutor.setCorePoolSize(5);
        // 设置最大线程数 最大支持多少个线程
        taskExecutor.setMaxPoolSize(200);
        // 设置队列容量 存储任务的容器
        taskExecutor.setQueueCapacity(500);
        // 设置线程活跃时间（秒）线程池维护线程所允许的空闲时间，超过这个时间就会释放
        taskExecutor.setKeepAliveSeconds(300);
        // 设置默认线程名称
        taskExecutor.setThreadNamePrefix("mz-task-");
        // 设置拒绝策略 // 线程池对拒绝任务（无线程可用）的处理策略，目前只支持AbortPolicy、CallerRunsPolicy；默认为后者
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        //等待时长
        taskExecutor.setAwaitTerminationSeconds(60);
        taskExecutor.initialize();
        return taskExecutor;
    }
}
